<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>GlslCanvas</title>

        <script type="text/javascript" src="dist/GlslCanvas.js"></script>
        <script type="text/javascript" src="https://cdn.rawgit.com/github/fetch/master/fetch.js"></script>

        <style>
            body {
                background: #101515;
            }

            #glslCanvas {
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%,-50%);
            }​

            .blank {

            }

            #credits {
                position: absolute; 
                bottom: 10px; 
                right: 15px; 
                text-align: right;
                background: rgba(0,0,0,.5);
                padding: 12px;
                padding-top: 5px;
                padding-bottom: 5px;
                margin: 0px
            }

            .label {
                color: white;
                font-family: Helvetica, Arial, sans-serif;
                text-decoration: none; 
                line-height: 0.0;
            }

            #title {
                font-size: 24px;
                font-weight: 600;
            }

            #author {
                font-size: 14px; 
                font-style: italic;
                font-weight: 100;
            }
        </style>

    </head>
    <body>
        <canvas id="glslCanvas" data-fragment="
// Author: Patricio Gonzalez Vivo
#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.1415926535
#define HALF_PI 1.57079632679

uniform vec2 u_resolution;
uniform float u_time;
uniform sampler2D u_tex0;
uniform vec2 u_tex0Resolution; 

uniform sampler2D u_logo; // data/logo.jpg
uniform vec2 u_logoResolution;

vec2 scale(vec2 st, float s) {
    return (st-.5)*s+.5;
}

vec2 ratio(in vec2 st, in vec2 s) {
    return mix( vec2((st.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,st.y),
                vec2(st.x,st.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),
                step(s.x,s.y));
}

float circleSDF(vec2 st) {
    return length(st - 0.5) * 2.0;
}

vec2 sphereCoords(vec2 _st, float _scale){
    float maxFactor = sin(1.570796327);
    vec2 uv = vec2(0.0);
    vec2 xy = 2.0 * _st.xy - 1.0;
    float d = length(xy);
    if (d < (2.0-maxFactor)){
        d = length(xy * maxFactor);
        float z = sqrt(1.0 - d * d);
        float r = atan(d, z) / 3.1415926535 * _scale;
        float phi = atan(xy.y, xy.x);
        uv.x = r * cos(phi) + 0.5;
        uv.y = r * sin(phi) + 0.5;
    } else {
        uv = _st.xy;
    }
    return uv;
}

vec4 sphereTexture(in sampler2D _tex, in vec2 _uv, float _time) {
    vec2 st = sphereCoords(_uv, 1.0);
    float aspect = u_tex0Resolution.y/u_tex0Resolution.x;
    st.x = fract(st.x * aspect + _time);
    return texture2D(_tex, st);
}

vec3 sphereNormals(in vec2 uv) {
    uv = fract(uv)*2.0-1.0; 
    vec3 ret;
    ret.xy = sqrt(uv * uv) * sign(uv);
    ret.z = sqrt(abs(1.0 - dot(ret.xy,ret.xy)));
    ret = ret * 0.5 + 0.5;    
    return mix(vec3(0.0), ret, smoothstep(1.0,0.98,dot(uv,uv)) );
}

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st = scale(st, 2.0);
    st = ratio(st, u_resolution);

    vec3 color = vec3(0.0);
    color = sphereTexture(u_tex0, st, u_time * 0.01).rgb;

    // Calculate sun direction
    float speedSun = 0.25;
    vec3 sunPos = normalize(vec3(cos(u_time * speedSun - HALF_PI), 0.0, sin(speedSun * u_time - HALF_PI)));
    vec3 surface = normalize(sphereNormals(st)*2.0-1.0);
   
    // Add Shadows
    color *= clamp(dot(sunPos, surface), 0.0, 1.0);
    // Blend black the edge of the sphere
    float radius = 1.0 - circleSDF(st);
    color *= smoothstep(0.001, 0.02, radius);

    st = scale(st, 2.);
    color += texture2D(u_logo, st).rgb * step(.0001,st.y) * step(st.y,.999);

    gl_FragColor = vec4(color, 1.0);
}
" width="800" height="600" data-textures="data/moon.jpg"></canvas>

        <div id="credits">
            <p class="label" id="title"></p>
            <p class="label" id="author"></p>
        </div>
    </body>

    <script>
        var canvas = document.getElementById("glslCanvas");
        var sandbox = new GlslCanvas(canvas);
        var texCounter = 0;
        var sandbox_content = "";
        var sandbox_title = "";
        var sandbox_author = "";
        var sandbox_thumbnail = ""; 
        canvas.style.width = '100%';
        canvas.style.height = '100%';

        function parseQuery (qstr) {
            var query = {};
            var a = qstr.split('&');
            for (var i in a) {
                var b = a[i].split('=');
                query[decodeURIComponent(b[0])] = decodeURIComponent(b[1]);
            }
            return query;
        }

        function load(url) {
            // Make the request and wait for the reply
            fetch(url)
                .then(function (response) {
                    // If we get a positive response...
                    if (response.status !== 200) {
                        console.log('Error getting shader. Status code: ' + response.status);
                        return;
                    }
                    // console.log(response);
                    return response.text();
                })
                .then(function(content) {
                    sandbox_content = content;
                    sandbox.load(content);

                    var title = addTitle();
                    var author = addAuthor();
                    if ( title === "unknown" && author === "unknown") {
                        document.getElementById("credits").style.visibility = "hidden";
                    } else {
                        document.getElementById("credits").style.visibility = "visible";
                    }

                    addMeta({
                                'title' : title + ' by ' + author,
                                'type' : 'website',
                                'url': window.location.href,
                                'image': sandbox_thumbnail
                            })                 
                })
        }

        function addTitle() {
            var result = sandbox_content.match(/\/\/\s*[T|t]itle\s*:\s*([\w|\s|\@|\(|\)|\-|\_]*)/i);
            if (result && !(result[1] === ' ' || result[1] === '')) {
                sandbox_title = result[1].replace(/(\r\n|\n|\r)/gm, '');
                var title_el = document.getElementById("title").innerHTML = sandbox_title;
                return sandbox_title;
            }
            else {
                return "unknown";
            }
        }

        function addAuthor() {
            var result = sandbox_content.match(/\/\/\s*[A|a]uthor\s*[\:]?\s*([\w|\s|\@|\(|\)|\-|\_]*)/i);
            if (result && !(result[1] === ' ' || result[1] === '')) {
                sandbox_author = result[1].replace(/(\r\n|\n|\r)/gm, '');
                document.getElementById("author").innerHTML = sandbox_author;
                return sandbox_author;
            }
            else {
                return "unknown";
            }
        }

        function addMeta(obj) {
            for (var key in obj) {
                var meta = document.createElement('meta');
                meta.setAttribute('og:'+key, obj[key]);
                document.getElementsByTagName('head')[0].appendChild(meta);
            }              
        }

        var query = parseQuery(window.location.search.slice(1));
        if (query && query.log) {
            sandbox_thumbnail = 'https://thebookofshaders.com/log/' + query.log + '.png';
            load('https://thebookofshaders.com/log/' + query.log + '.frag');
        }

        if (window.location.hash !== '') {
            var hashes = location.hash.split('&');
            for (var i in hashes) {
                var ext = hashes[i].substr(hashes[i].lastIndexOf('.') + 1);
                var path = hashes[i];

                // Extract hash if is present
                if (path.search('#') === 0) {
                    path = path.substr(1);
                }

                if (ext === 'frag') {
                    load(path);
                }
                else if (ext === 'png' || ext === 'jpg' || ext === 'PNG' || ext === 'JPG') {
                    sandbox.setUniform("u_tex"+texCounter.toString(), path);
                    texCounter++;
                }
            }
        }
    </script>
    <script>
        (function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,"script","//www.google-analytics.com/analytics.js","ga");
        ga("create", "UA-18824436-2", "auto");
        ga("send", "pageview");
    </script>
</html>